﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using System.Reflection;

namespace SPWorkflows
{
    public partial class Form1 : Form
    {
        public static object instanceId = null;
        public static SPListItem itemForActivityDetails = null;
        public string siteUrl;
        public string listChoice = string.Empty;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }

        /// <summary>
        /// List all the List Name
        /// </summary>
        /// <param name="cmbList"></param>
        private void FillList(ComboBox cmbList)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    try
                    {
                        using (SPSite site = new SPSite(siteUrl))
                        {
                            SPWeb web = site.OpenWeb();
                            foreach (SPList list in web.Lists)
                            {
                                cmbList.Items.Add(list.Title);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message + " Error ID HEX001", "Error Information");
                    }

                });
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// Will display the WorkflowAssociations of the selected list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                dataGridView1.Visible = false;
                cmbAssociationId.Items.Clear();
                cmbAssociationId.Text = "";
                ClearCounter();

                listChoice = cmbList.SelectedItem.ToString();
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    try
                    {
                        using (SPSite site = new SPSite(siteUrl))
                        {
                            SPWeb web = site.OpenWeb();
                            SPList list = web.Lists[listChoice];
                            //Get the SPWorkflowAssociation Item Name based on the selected list
                            foreach (SPWorkflowAssociation item in list.WorkflowAssociations)
                            {
                                cmbAssociationId.Items.Add(item.Name);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message + " Error ID HEX002", "Error Information");
                    }
                });
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Get SPWorkflowState and Workflow Status
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnWf_Click(object sender, EventArgs e)
        {
            #region Get the Workflow Association Id
            try
            {
                ClearCounter();
                dataGridView1.Visible = true;
                Guid cus = Guid.Empty;
                string workflowName = string.Empty;
                int countCompleted = 0;
                int countRunning = 0;
                int countLocked = 0;
                int countTerminated = 0;
                int countExpired = 0;
                int countHasEvents = 0;
                int countNotStarted = 0;
                int countCancelled = 0;
                int count_NotStarted = 0;
                int count_FailedOnStart = 0;
                int count_InProgress = 0;
                int count_ErrorOccurred = 0;
                int count_StoppedByUser = 0;
                int count_Completed = 0;
                int count_FailedOnStartRetrying = 0;
                int count_ErrorOccurredRetrying = 0;
                int count_ViewQueryOverflow = 0;

                List<SRWorkflow> srw = new List<SRWorkflow>();

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    try
                    {
                        using (SPSite site = new SPSite(siteUrl))
                        {
                            string getworkflowParentAssociationName = cmbAssociationId.SelectedItem.ToString();
                            SPWeb web = site.OpenWeb();
                            SPList list = web.Lists[listChoice];

                            //Get ID of the Associated Workflow
                            foreach (SPWorkflowAssociation item in list.WorkflowAssociations)
                            {
                                if (getworkflowParentAssociationName == item.Name)
                                {
                                    cus = item.Id;
                                    workflowName = item.Name.ToString();
                                }
                            }

                            //Method to get Workflow State and Status
                            foreach (SPListItem item in list.Items)
                            {

                                itemForActivityDetails = item;

                                foreach (SPWorkflow workflow in item.Workflows)
                                {
                                    if (workflow.AssociationId == cus)
                                    {
                                        if (list.Fields.ContainsField(workflowName))
                                        {

                                            var WorkflowStatusValue = item[workflowName];

                                            string WorkflowStatusString = System.Enum.GetName(typeof(SPWorkflowStatus), Convert.ToInt32(WorkflowStatusValue));

                                            srw.Add(new SRWorkflow(workflow.ItemName.ToString(), workflow.InternalState.ToString(), WorkflowStatusString, workflow.Created.ToString(), workflow.IsCompleted.ToString(), workflow.IsLocked.ToString(), workflow.ParentAssociation.Name, workflow.InstanceId.ToString()));

                                            #region Switch Case for Workflow STATE
                                            SPWorkflowState getState = workflow.InternalState;
                                            switch (getState)
                                            {
                                                case SPWorkflowState.Completed:
                                                    countCompleted++;
                                                    txtCompleted.Text = countCompleted.ToString();
                                                    break;
                                                case SPWorkflowState.Running:
                                                    countRunning++;
                                                    txtRunning.Text = countRunning.ToString();
                                                    break;
                                                case SPWorkflowState.Locked:
                                                    countLocked++;
                                                    txtLocked.Text = countLocked.ToString();
                                                    break;
                                                case SPWorkflowState.Terminated:
                                                    countTerminated++;
                                                    txtTerminated.Text = countTerminated.ToString();
                                                    break;
                                                case SPWorkflowState.Expired:
                                                    countExpired++;
                                                    txtExpired.Text = countExpired.ToString();
                                                    break;
                                                case SPWorkflowState.HasNewEvents:
                                                    countHasEvents++;
                                                    txtHasEvents.Text = countHasEvents.ToString();
                                                    break;
                                                case SPWorkflowState.NotStarted:
                                                    countNotStarted++;
                                                    txtNotstarted.Text = countNotStarted.ToString();
                                                    break;
                                                case SPWorkflowState.Cancelled:
                                                    countCancelled++;
                                                    txtCancelled.Text = countCancelled.ToString();
                                                    break;

                                            }
                                            #endregion Switch Case for Workflow STATE

                                            #region Switch Case for Workflow STATUS
                                            switch (WorkflowStatusString)
                                            {
                                                case "NotStarted":
                                                    count_NotStarted++;
                                                    txt_NotStarted.Text = count_NotStarted.ToString();
                                                    break;
                                                case "FailedOnStart":
                                                    count_FailedOnStart++;
                                                    txt_FailedOnStart.Text = count_FailedOnStart.ToString();
                                                    break;
                                                case "InProgress":
                                                    count_InProgress++;
                                                    txt_InProgress.Text = count_InProgress.ToString();
                                                    break;
                                                case "ErrorOccurred":
                                                    count_ErrorOccurred++;
                                                    txt_ErrorOccurred.Text = count_ErrorOccurred.ToString();
                                                    break;
                                                case "StoppedByUser":
                                                    count_StoppedByUser++;
                                                    txt_StoppedByUser.Text = count_StoppedByUser.ToString();
                                                    break;
                                                case "Completed":
                                                    count_Completed++;
                                                    txt_Completed.Text = count_Completed.ToString();
                                                    break;
                                                case "FailedOnStartRetrying":
                                                    count_FailedOnStartRetrying++;
                                                    txt_FailedOnStartRetrying.Text = count_FailedOnStartRetrying.ToString();
                                                    break;
                                                case "ErrorOccurredRetrying":
                                                    count_ErrorOccurredRetrying++;
                                                    txt_ErrorOccurredRetrying.Text = count_ErrorOccurredRetrying.ToString();
                                                    break;
                                                case "ViewQueryOverflow":
                                                    count_ViewQueryOverflow++;
                                                    txt_ViewQueryOverflow.Text = count_ViewQueryOverflow.ToString();
                                                    break;
                                            }
                                            #endregion Switch Case for Workflow STATUS

                                        }

                                    }

                                }

                            }

                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message + " Error ID HEX003", "Error Information");
                    }
                });
                DataTable dt = ToDataTable(srw);
                dataGridView1.DataSource = dt;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + " Error ID HEX003", "Error Information");
            }
            #endregion Get the Workflow Association Id
        }

        #region Utilities

        private void btnLists_Click(object sender, EventArgs e)
        {
            try
            {
                siteUrl = txtSiteUrl.Text;
                FillList(cmbList);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + " Error ID HEX004", "Error Information");
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            try
            {
                frmRestartWorkflows frmRestart = new frmRestartWorkflows();
                frmRestart.listName = cmbList.Text;
                frmRestart.workflowName = cmbAssociationId.Text;
                frmRestart.siteName = txtSiteUrl.Text;
                frmRestart.ShowDialog();
            }
            catch (Exception ex)
            {
            }
            

        }

        private void ClearCounter()
        {
            try
            {
                txtCancelled.Text = "";
                txtCompleted.Text = "";
                txtExpired.Text = "";
                txtHasEvents.Text = "";
                txtLocked.Text = "";
                txtNotstarted.Text = "";
                txtRunning.Text = "";
                txtTerminated.Text = "";

                txt_Completed.Text = "";
                txt_ErrorOccurred.Text = "";
                txt_ErrorOccurredRetrying.Text = "";
                txt_FailedOnStart.Text = "";
                txt_FailedOnStartRetrying.Text = "";
                txt_InProgress.Text = "";
                txt_NotStarted.Text = "";
                txt_StoppedByUser.Text = "";
                txt_ViewQueryOverflow.Text = "";
            }
            catch (Exception ex)
            {
            }
            
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            //instanceId = dataGridView1.Rows[e.RowIndex].Cells[7].Value;
            //frnActivityDetails frnAD = new frnActivityDetails();
            //frnAD.Show();
        }
        
        #region Convert a List{T} to a DataTable.
        /// <summary>
        /// Convert a List{T} to a DataTable.
        /// </summary>
        private DataTable ToDataTable<T>(List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);

            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo prop in props)
            {
                Type t = GetCoreType(prop.PropertyType);
                tb.Columns.Add(prop.Name, t);
            }

            foreach (T item in items)
            {
                var values = new object[props.Length];

                for (int i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                tb.Rows.Add(values);
            }
            return tb;
        }

        /// <summary>
        /// Determine of specified type is nullable
        /// </summary>
        public static bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        /// <summary>
        /// Return underlying type if type is Nullable otherwise return the type
        /// </summary>
        public static Type GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }
        #endregion Convert a List{T} to a DataTable.

        #endregion Utilities
    }
}
